package com.archermind.boc.socket.handler;

import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.ssl.SslFilter;
import org.apache.mina.filter.ssl.SslFilter.SslFilterMessage;

import com.archermind.boc.Logger;
import com.archermind.boc.dal.business.impl.DispatchImpl;
import com.archermind.boc.utils.UtilsTools;
import com.archermind.boc.xml.Protocol;
import com.archermind.boc.xml.parser.impl.XMLParser;

public class BOCSServerHandler extends IoHandlerAdapter {

	final static XMLParser parser = new XMLParser();

	private final static Logger logger = Logger.getLogger(BOCSServerHandler.class.getName());

	final static CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();

	public void sessionCreated(IoSession session) throws Exception {
		session.setAttribute(SslFilter.USE_NOTIFICATION);
		CacheSession.addSession(session);
		logger.info("[  Created] [" + CacheSession.getSessionID(session.getId()) + "]");
	}

	public void sessionOpened(IoSession session) throws Exception {
		logger.info("[   Opened] [" + CacheSession.getSessionID(session.getId()) + "]");
	}

	public void sessionClosed(IoSession session) throws Exception {
		logger.info("[   Closed] [" + CacheSession.getSessionID(session.getId()) + "]");
		if (CacheSession.isExistSession(session.getId())) {
			DispatchImpl.dispatch(CacheSession.getSessionID(session.getId()));
			CacheSession.removeSession(session.getId());
		}
	}

	public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
		logger.info("[     Idle] [" + CacheSession.getSessionID(session.getId()) + "]");
	}

	public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
		logger.error("[Exception]", new Exception(cause));
		if(!session.isConnected()){
			DispatchImpl.dispatch(CacheSession.getSessionID(session.getId()));
			CacheSession.removeSession(session.getId());
		}
	}

	public void messageReceived(IoSession session, Object message) throws Exception {
		String msg = "";
		if (message instanceof SslFilterMessage) {
			msg = ((SslFilterMessage) message).toString();
		} else if (message instanceof IoBuffer) {
			msg = ((IoBuffer) message).getString(decoder);
			if (validate(session, msg)) {
				msg = (String) session.getAttribute("protocol");
				logger.info("[ Received] [" + session.getId() + "] [" + msg + "]");
				session.setAttribute("protocol", null);
				if (msg.startsWith("<stream")) {
					session.write(UtilsTools.getIoBuffer(Protocol.server1_0)).awaitUninterruptibly();
					session.write(UtilsTools.getIoBuffer(Protocol.server1_1)).awaitUninterruptibly();
				} else if (msg.startsWith("</stream:stream>")) {
					DispatchImpl.dispatchLogOut(CacheSession.getSessionID(session.getId()));
					CacheSession.removeSession(session.getId());
					session.write(UtilsTools.getIoBuffer(msg)).awaitUninterruptibly();
				} else {
					parser.parse(CacheSession.getSessionID(session.getId()), msg);
				}
				// if (msg.startsWith("<auth")) {
				// session.write(UtilsTools.getIoBuffer(Protocol.server2)).awaitUninterruptibly();
				// } else if (msg.startsWith("<iq to=")) {
				// session.write(UtilsTools.getIoBuffer(Protocol.server3)).awaitUninterruptibly();
				// session.write(UtilsTools.getIoBuffer(Protocol.server4)).awaitUninterruptibly();
				// } else if (msg.startsWith("<message") &&
				// msg.indexOf("<body>") != -1) {
				// session.write(UtilsTools.getIoBuffer(Protocol.server5)).awaitUninterruptibly();
				// } else if (msg.startsWith("<iq from")) {
				// session.write(UtilsTools.getIoBuffer(msg)).awaitUninterruptibly();
				// }
			} else {
				logger.info("[ Received] [" + CacheSession.getSessionID(session.getId()) + "] [Protocol Unfinished ]");
			}
		}
		// logger.info("[ Received] [" + session.getRemoteAddress() +
		// "] [" + session.getId() + "] [" + msg + "]");
	}

//	public void messageSent(IoSession session, Object message) throws Exception {
//		String msg = ((IoBuffer) message).getString(decoder);
//		if (msg != null && !msg.startsWith("<message")) {
//			logger.info("[     Sent] [" + session.getRemoteAddress() + "] [" + session.getId() + "] [" + msg + "]");
//		}
//	}

	public static boolean validate(IoSession session, String msg) {
		boolean flag = false;
		String protocol = msg;
		String tempProtocol = msg;
		if (msg.startsWith("<stream:stream") && msg.endsWith(">")) {
			flag = true;
		} else if (msg.startsWith("</stream:stream>")) {
			flag = true;
		} else {
			protocol = (String) session.getAttribute("protocol");
			protocol = protocol == null ? msg : protocol + msg;
			tempProtocol = protocol;
			if (tempProtocol.endsWith(">") && tempProtocol.startsWith("<")) {
				int index = tempProtocol.indexOf(">");
				String temp = tempProtocol.substring(1, index);
				if (temp.indexOf(" ") != -1) {
					index = temp.indexOf(" ");
					temp = temp.substring(0, index);
				}
				//fix bug of out of array length
				if (tempProtocol.endsWith("</" + temp + ">")) {
					flag = true;
				}
			}
		}
		session.setAttribute("protocol", protocol);
		return flag;
	}
}
